﻿#include "mythread.h"
#include "myserver.h"
#include "mysocket.h"
#include "mainwindow.h"

#include <QHostInfo>

#if _MSC_VER >=1600
#pragma execution_character_set("utf-8")
#endif

MyThread::MyThread(QObject *parent)
{
    this->myserver=static_cast<MyServer*>(parent);
    this->sockethelper=nullptr;
    this->ThreadLoad = 0;
}

MyThread::~MyThread()
{
     if(this->sockethelper!=nullptr)
     {
        sockethelper->disconnect();
        delete this->sockethelper;  //释放sockethelper
     }
}

void MyThread::run()
{
    //在线程内创建对象，槽函数在这个线程中执行
    this->sockethelper=new SocketHelper(this->myserver);
    connect(sockethelper,&SocketHelper::Create,sockethelper,&SocketHelper::CreateSocket);
    connect(sockethelper,&SocketHelper::AddList,myserver,&MyServer::AddInf);
    connect(sockethelper,&SocketHelper::RemoveList,myserver,&MyServer::RemoveInf);

    exec();
}

SocketHelper::SocketHelper(QObject *parent)
{
    this->myserver=static_cast<MyServer*>(parent);

}

void SocketHelper::CreateSocket(qintptr socketDescriptor,int index)
{
    qDebug()<<"subThread:"<<QThread::currentThreadId();

    MySocket* tcpsocket = new MySocket(this->myserver);
    tcpsocket->sockethelper = this;
    //初始化socket
    tcpsocket->setSocketDescriptor(socketDescriptor);
    //发送到UI线程记录信息
    emit AddList(tcpsocket,index);//

    if( index!= -1)//非UI线程时
    {
        //负载+1
        myserver->list_thread[index]->ThreadLoad+=1;//负载+1
        //关联释放socket,非UI线程需要阻塞
        connect(tcpsocket , &MySocket::DeleteSocket , tcpsocket, &MySocket::deal_disconnect,Qt::ConnectionType::BlockingQueuedConnection);
    }
    else
    {
       connect(tcpsocket , &MySocket::DeleteSocket , tcpsocket, &MySocket::deal_disconnect,Qt::ConnectionType::AutoConnection);
    }

    //关联显示消息
    connect(tcpsocket,&MySocket::AddMessage,myserver->tcpserverassistant,&TcpServerAssistant::on_add_serverMessage);
    //发送消息
    connect(tcpsocket,&MySocket::WriteMessage,tcpsocket,&MySocket::deal_write);
    //关联接收数据
    connect(tcpsocket , &MySocket::readyRead , tcpsocket , &MySocket::deal_readyRead);
    //关联断开连接时的处理槽
    connect(tcpsocket , &MySocket::disconnected , tcpsocket, &MySocket::deal_disconnect);

    QString ip = tcpsocket->peerAddress().toString();
    quint16 port = tcpsocket->peerPort();
    QString message = QString("[%1:%2] 已连接").arg(ip).arg(port);
    //发送到UI线程显示
    emit tcpsocket->AddMessage(message);



}

//获取本地IP
QString SocketHelper::Get_LocalIp()
{
    QString hostName=QHostInfo::localHostName();            //本地主机名
    QHostInfo hostInfo=QHostInfo::fromName(hostName);       //本机IP地址
    QList<QHostAddress> addList=hostInfo.addresses();      //IP地址列表
    for (int i=0;i<addList.count();i++)
    {
        QHostAddress aHost=addList.at(i); //每一项是一个QHostAddress
        if(QAbstractSocket::IPv4Protocol==aHost.protocol())
        {
            return aHost.toString(); //显示出Ip地址
        }
    }
    return QString("");
}
//字节数组转16进制字符串
void SocketHelper::ByteToHexString(QString &str, QByteArray &ba)
{
    //str= ba.toHex();//直接转换中间没有空格
    for (int i = 0; i < ba.length(); i++)
    {
        unsigned char n =static_cast<unsigned char>((ba.at(i)));
        QString nhex = QByteArray::number(n, 16).toUpper();
        str.append(nhex);
        str.append(' ');//字节间加空格
    }
}

//16进制字符串转字节数组
//str：输入字符串，ba：输出字节数组
bool SocketHelper::HexStringToByte(QString &str,QByteArray &ba)
{
    QString pattern("[a-fA-F0-9]+");//正则:数字0-9字母a-f、A-F匹配大于等于一次
    QRegExp rx(pattern);
    str = str.replace(' ', "");//删除所有空格
    if (rx.exactMatch(str))//匹配
    {
        bool ok;
        int length = str.length();
        if ((length % 2)==0)//双数
        {
            for (int i = 0; i < length; i+=2)
            {
                QString str_hex = str.mid(i, 2);//每两个字符对应一个hex字符串
                ba.append(static_cast<char>(str_hex.toInt(&ok, 16)));//hex字符串转整数值
            }
        }
        else//单数
        {
            for (int i = 0; i < length-1; i += 2)
            {
                QString str_hex = str.mid(i, 2);//每两个字符对应一个hex字符串
                ba.append(static_cast<char>(str_hex.toInt(&ok, 16)));//hex字符串转整数值
            }
            //最后一个单独处理
            ba.append(static_cast<char>(str.mid(length - 1,1).toInt(&ok, 16)));//hex字符串转整数值
        }
        return true;
    }
    else
    {
        return false;
    }
}

